# ui/table_window.py
import logging
from PySide6.QtWidgets import (
    QDialog, QVBoxLayout, QTableView, QToolBar, QLabel,
    QFileDialog, QMessageBox, QSplitter, QTabWidget, QWidget, QGridLayout,
    QHBoxLayout, QGroupBox, QLineEdit, QComboBox, QCheckBox, QPushButton,
    QHeaderView, QMenu, QApplication, QProgressDialog, QSpinBox,
    QDialogButtonBox, QFormLayout, QFrame, QToolButton, QSizePolicy
)
from PySide6.QtCore import Qt, QSortFilterProxyModel, QTimer, Signal, Slot
from PySide6.QtGui import QStandardItemModel, QStandardItem, QActionGroup, QCursor, QAction
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.figure import Figure
import os
import re
from .base_widget import BaseWidgetMixin

# 配置日志记录
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')


class TableWindow(QDialog, BaseWidgetMixin):
    """表格窗口，用于显示和操作数据"""

    def __init__(self, well_name, data, parent=None):
        super().__init__(parent)

        self.setWindowTitle(f"井数据 - {well_name}")
        self.setGeometry(100, 100, 1200, 800)

        self.well_name = well_name
        self.original_data = data.copy()
        self.filtered_data = data.copy()

        # 用于存储统计图表的画布
        self.canvas_widgets = []

        # 初始化UI
        self._init_ui()

    def _init_ui(self):
        """初始化UI组件"""
        main_layout = QVBoxLayout(self)

        # 工具栏
        toolbar = QToolBar("表格工具")
        main_layout.addWidget(toolbar)

        # 搜索框
        search_action = QAction("搜索", self)
        search_action.triggered.connect(self._show_search_panel)
        toolbar.addAction(search_action)

        # 导出数据
        export_action = QAction("导出", self)
        export_action.triggered.connect(self._export_table_data)
        toolbar.addAction(export_action)

        # 刷新数据
        refresh_action = QAction("刷新", self)
        refresh_action.triggered.connect(self._refresh_table)
        toolbar.addAction(refresh_action)

        # 添加统计图表按钮
        stats_action = QAction("统计图表", self)
        stats_action.triggered.connect(self._show_stats_charts)
        toolbar.addAction(stats_action)

        # 分割器
        splitter = QSplitter(Qt.Vertical)

        # 表格视图
        self.table_view = QTableView()
        self.table_view.setSortingEnabled(True)
        self.table_view.setSelectionBehavior(QTableView.SelectRows)
        self.table_view.setSelectionMode(QTableView.ExtendedSelection)
        self.table_view.setAlternatingRowColors(True)
        self.table_view.setContextMenuPolicy(Qt.CustomContextMenu)
        self.table_view.customContextMenuRequested.connect(self._show_table_context_menu)
        splitter.addWidget(self.table_view)

        # 数据统计和可视化标签页
        stats_tab = QTabWidget()

        # 统计信息面板
        self.stats_widget = QWidget()
        self.stats_layout = QVBoxLayout(self.stats_widget)
        stats_tab.addTab(self.stats_widget, "统计信息")

        # 数据可视化面板
        self.visualization_widget = QWidget()
        self.visualization_layout = QVBoxLayout(self.visualization_widget)
        stats_tab.addTab(self.visualization_widget, "数据可视化")

        splitter.addWidget(stats_tab)

        # 设置分割器比例
        splitter.setSizes([700, 300])

        main_layout.addWidget(splitter)

        # 状态栏
        self.status_label = QLabel()
        main_layout.addWidget(self.status_label)

        # 加载数据到表格
        self._load_data_to_table()

        # 更新状态栏
        self._update_status()

    def _load_data_to_table(self):
        """加载数据到表格模型"""
        self.model = QStandardItemModel()
        self.model.setHorizontalHeaderLabels(self.filtered_data.columns.tolist())

        # 创建进度对话框
        progress = QProgressDialog("加载数据...", "取消", 0, len(self.filtered_data), self)
        progress.setWindowTitle("加载数据")
        progress.setWindowModality(Qt.WindowModal)
        progress.setMinimumDuration(500)
        progress.show()

        # 填充数据
        for row_idx, (_, row) in enumerate(self.filtered_data.iterrows()):
            if progress.wasCanceled():
                break

            items = [QStandardItem(str(value)) for value in row.values]
            for item in items:
                item.setEditable(False)
            self.model.appendRow(items)

            # 更新进度
            if row_idx % 100 == 0:
                progress.setValue(row_idx)
                QApplication.processEvents()

        progress.close()

        # 应用筛选模型
        self.proxy_model = QSortFilterProxyModel()
        self.proxy_model.setSourceModel(self.model)
        self.proxy_model.setFilterCaseSensitivity(Qt.CaseInsensitive)
        self.proxy_model.setDynamicSortFilter(True)

        self.table_view.setModel(self.proxy_model)
        self.table_view.resizeColumnsToContents()

        # 更新统计信息
        self._update_stats()

    def _update_status(self):
        """更新状态栏信息"""
        total_rows = self.filtered_data.shape[0]
        total_cols = self.filtered_data.shape[1]

        selected_rows = len(self.table_view.selectionModel().selectedRows())

        if selected_rows > 0:
            self.status_label.setText(f"共 {total_rows} 行 {total_cols} 列，选中 {selected_rows} 行")
        else:
            self.status_label.setText(f"共 {total_rows} 行 {total_cols} 列")

    def _update_stats(self):
        """更新数据统计信息"""
        # 清除之前的统计信息
        while self.stats_layout.count():
            item = self.stats_layout.takeAt(0)
            widget = item.widget()
            if widget:
                widget.deleteLater()

        # 检查是否有数据
        if self.filtered_data.empty:
            self.stats_label = QLabel("没有数据可供分析")
            self.stats_layout.addWidget(self.stats_label)
            return

        # 创建统计信息表格
        stats_group = QGroupBox("基本统计信息")
        stats_layout = QGridLayout(stats_group)

        # 计算基本统计量
        numeric_cols = self.filtered_data.select_dtypes(include=[np.number]).columns

        row = 0
        for col in numeric_cols:
            try:
                stats_layout.addWidget(QLabel(f"<b>{col}</b>"), row, 0)

                # 均值
                mean = self.filtered_data[col].mean()
                stats_layout.addWidget(QLabel(f"均值: {mean:.4f}"), row, 1)

                # 中位数
                median = self.filtered_data[col].median()
                stats_layout.addWidget(QLabel(f"中位数: {median:.4f}"), row, 2)

                # 标准差
                std = self.filtered_data[col].std()
                stats_layout.addWidget(QLabel(f"标准差: {std:.4f}"), row, 3)

                # 最小值
                min_val = self.filtered_data[col].min()
                stats_layout.addWidget(QLabel(f"最小值: {min_val:.4f}"), row + 1, 1)

                # 最大值
                max_val = self.filtered_data[col].max()
                stats_layout.addWidget(QLabel(f"最大值: {max_val:.4f}"), row + 1, 2)

                # 分位数
                q25 = self.filtered_data[col].quantile(0.25)
                q75 = self.filtered_data[col].quantile(0.75)
                stats_layout.addWidget(QLabel(f"25%分位: {q25:.4f}"), row + 2, 1)
                stats_layout.addWidget(QLabel(f"75%分位: {q75:.4f}"), row + 2, 2)

                row += 3
            except Exception as e:
                logging.error(f"计算 {col} 列统计信息时出错: {e}")
                continue

        self.stats_layout.addWidget(stats_group)

        # 更新数据可视化
        self._update_visualization()

    def _update_visualization(self):
        """更新数据可视化"""
        # 清除之前的可视化
        while self.visualization_layout.count():
            item = self.visualization_layout.takeAt(0)
            widget = item.widget()
            if widget:
                widget.deleteLater()

        # 检查是否有数据
        if self.filtered_data.empty:
            self.visualization_label = QLabel("没有数据可供可视化")
            self.visualization_layout.addWidget(self.visualization_label)
            return

        # 创建图表选择器
        chart_type_layout = QHBoxLayout()
        chart_type_label = QLabel("选择图表类型:")
        chart_type_combo = QComboBox()
        chart_type_combo.addItems(["直方图", "散点图", "折线图", "箱线图"])
        chart_type_combo.currentTextChanged.connect(self._create_chart)

        # 添加列选择下拉框
        column1_combo = QComboBox()
        column2_combo = QComboBox()

        numeric_cols = self.filtered_data.select_dtypes(include=[np.number]).columns.tolist()
        column1_combo.addItems(numeric_cols)
        column2_combo.addItems(numeric_cols)

        chart_type_layout.addWidget(chart_type_label)
        chart_type_layout.addWidget(chart_type_combo)
        chart_type_layout.addWidget(QLabel("X轴:"))
        chart_type_layout.addWidget(column1_combo)
        chart_type_layout.addWidget(QLabel("Y轴:"))
        chart_type_layout.addWidget(column2_combo)

        # 添加刷新按钮
        refresh_btn = QPushButton("刷新图表")
        refresh_btn.clicked.connect(lambda: self._create_chart(
            chart_type_combo.currentText(),
            column1_combo.currentText(),
            column2_combo.currentText()
        ))
        chart_type_layout.addWidget(refresh_btn)

        self.visualization_layout.addLayout(chart_type_layout)

        # 创建初始图表
        if numeric_cols:
            self._create_chart(chart_type_combo.currentText(), numeric_cols[0], numeric_cols[0])

    def _create_chart(self, chart_type, column1, column2=None):
        """创建图表"""
        # 清除之前的图表
        for canvas in self.canvas_widgets:
            self.visualization_layout.removeWidget(canvas)
            canvas.deleteLater()
        self.canvas_widgets = []

        # 检查是否有数据
        if self.filtered_data.empty:
            self.visualization_label = QLabel("没有数据可供可视化")
            self.visualization_layout.addWidget(self.visualization_label)
            return

        # 确保列存在
        if column1 not in self.filtered_data.columns:
            self.show_warning(f"列 '{column1}' 不存在")
            return

        if column2 and column2 not in self.filtered_data.columns:
            self.show_warning(f"列 '{column2}' 不存在")
            return

        # 创建图表
        fig = Figure(figsize=(10, 4))

        if chart_type == "直方图":
            ax = fig.add_subplot(111)
            ax.hist(self.filtered_data[column1], bins=20, alpha=0.7)
            ax.set_title(f"{column1} 直方图")
            ax.set_xlabel(column1)
            ax.set_ylabel("频数")

        elif chart_type == "散点图":
            if not column2 or column2 == column1:
                # 如果没有选择第二列，默认使用第一列作为Y轴
                if len(self.filtered_data.select_dtypes(include=[np.number]).columns) > 1:
                    # 选择另一个数值列
                    numeric_cols = self.filtered_data.select_dtypes(include=[np.number]).columns.tolist()
                    column2 = numeric_cols[1] if numeric_cols[0] == column1 else numeric_cols[0]
                else:
                    self.show_warning("需要至少两个数值列来创建散点图")
                    return

            ax = fig.add_subplot(111)
            ax.scatter(self.filtered_data[column1], self.filtered_data[column2], alpha=0.5)
            ax.set_title(f"{column1} vs {column2}")
            ax.set_xlabel(column1)
            ax.set_ylabel(column2)

        elif chart_type == "折线图":
            if not column2 or column2 == column1:
                # 如果没有选择第二列，默认使用索引作为X轴
                ax = fig.add_subplot(111)
                ax.plot(self.filtered_data[column1])
                ax.set_title(f"{column1} 趋势图")
                ax.set_xlabel("索引")
                ax.set_ylabel(column1)
            else:
                ax = fig.add_subplot(111)
                ax.plot(self.filtered_data[column1], self.filtered_data[column2])
                ax.set_title(f"{column1} vs {column2}")
                ax.set_xlabel(column1)
                ax.set_ylabel(column2)

        elif chart_type == "箱线图":
            ax = fig.add_subplot(111)
            ax.boxplot(self.filtered_data[column1].dropna())
            ax.set_title(f"{column1} 箱线图")
            ax.set_ylabel(column1)

        # 添加图表到布局
        canvas = FigureCanvas(fig)
        canvas.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        self.visualization_layout.addWidget(canvas)
        self.canvas_widgets.append(canvas)

    def _show_search_panel(self):
        """显示搜索面板"""
        # 创建一个简单的搜索对话框
        search_dialog = QDialog(self)
        search_dialog.setWindowTitle("搜索")
        search_dialog.setMinimumWidth(400)

        layout = QVBoxLayout(search_dialog)

        # 搜索文本框
        search_layout = QHBoxLayout()
        search_layout.addWidget(QLabel("搜索内容:"))
        search_text = QLineEdit()
        search_layout.addWidget(search_text)
        layout.addLayout(search_layout)

        # 搜索选项
        options_layout = QGridLayout()

        # 搜索列选择
        options_layout.addWidget(QLabel("搜索列:"), 0, 0)
        column_combo = QComboBox()
        column_combo.addItems(["所有列"] + self.filtered_data.columns.tolist())
        options_layout.addWidget(column_combo, 0, 1)

        # 搜索方式选择
        options_layout.addWidget(QLabel("搜索方式:"), 1, 0)
        search_type_combo = QComboBox()
        search_type_combo.addItems(["包含", "等于", "大于", "小于", "起始于", "结束于"])
        options_layout.addWidget(search_type_combo, 1, 1)

        # 是否区分大小写
        case_sensitive_check = QCheckBox("区分大小写")
        options_layout.addWidget(case_sensitive_check, 2, 0, 1, 2)

        layout.addLayout(options_layout)

        # 按钮
        button_layout = QHBoxLayout()
        search_button = QPushButton("搜索")
        search_button.clicked.connect(lambda: self._perform_search(
            search_text.text(),
            column_combo.currentText(),
            search_type_combo.currentText(),
            case_sensitive_check.isChecked(),
            search_dialog
        ))
        button_layout.addWidget(search_button)

        cancel_button = QPushButton("取消")
        cancel_button.clicked.connect(search_dialog.reject)
        button_layout.addWidget(cancel_button)

        layout.addLayout(button_layout)

        search_dialog.setLayout(layout)
        search_dialog.exec_()

    def _perform_search(self, search_text, column, search_type, case_sensitive, dialog=None):
        """执行搜索"""
        if not search_text and search_type != "等于":  # 等于允许空值搜索
            self.show_warning("请输入搜索内容")
            return

        try:
            # 根据搜索条件过滤数据
            if column == "所有列":
                # 在所有列中搜索
                if search_type == "包含":
                    if case_sensitive:
                        mask = self.original_data.apply(lambda row: row.astype(str).str.contains(search_text).any(),
                                                        axis=1)
                    else:
                        mask = self.original_data.apply(
                            lambda row: row.astype(str).str.contains(search_text, case=False).any(), axis=1)
                elif search_type == "等于":
                    if case_sensitive:
                        mask = self.original_data.apply(lambda row: (row.astype(str) == search_text).any(), axis=1)
                    else:
                        mask = self.original_data.apply(
                            lambda row: (row.astype(str).str.lower() == search_text.lower()).any(), axis=1)
                elif search_type == "起始于":
                    if case_sensitive:
                        mask = self.original_data.apply(lambda row: row.astype(str).str.startswith(search_text).any(),
                                                        axis=1)
                    else:
                        mask = self.original_data.apply(
                            lambda row: row.astype(str).str.lower().str.startswith(search_text.lower()).any(), axis=1)
                elif search_type == "结束于":
                    if case_sensitive:
                        mask = self.original_data.apply(lambda row: row.astype(str).str.endswith(search_text).any(),
                                                        axis=1)
                    else:
                        mask = self.original_data.apply(
                            lambda row: row.astype(str).str.lower().str.endswith(search_text.lower()).any(), axis=1)
                else:
                    # 对于数值比较，需要选择一个数值列
                    numeric_cols = self.original_data.select_dtypes(include=[np.number]).columns
                    if not numeric_cols.empty:
                        col = numeric_cols[0]
                        try:
                            value = float(search_text)
                        except ValueError:
                            self.show_warning(f"无法将 '{search_text}' 转换为数值")
                            return

                        if search_type == "大于":
                            mask = self.original_data[col] > value
                        else:  # 小于
                            mask = self.original_data[col] < value
                    else:
                        self.show_warning("没有找到数值列，无法执行大于/小于搜索")
                        return
            else:
                # 在指定列中搜索
                if search_type == "包含":
                    if case_sensitive:
                        mask = self.original_data[column].astype(str).str.contains(search_text)
                    else:
                        mask = self.original_data[column].astype(str).str.contains(search_text, case=False)
                elif search_type == "等于":
                    if case_sensitive:
                        mask = self.original_data[column].astype(str) == search_text
                    else:
                        mask = self.original_data[column].astype(str).str.lower() == search_text.lower()
                elif search_type == "起始于":
                    if case_sensitive:
                        mask = self.original_data[column].astype(str).str.startswith(search_text)
                    else:
                        mask = self.original_data[column].astype(str).str.lower().str.startswith(search_text.lower())
                elif search_type == "结束于":
                    if case_sensitive:
                        mask = self.original_data[column].astype(str).str.endswith(search_text)
                    else:
                        mask = self.original_data[column].astype(str).str.lower().str.endswith(search_text.lower())
                else:
                    # 数值比较
                    try:
                        value = float(search_text)
                        if search_type == "大于":
                            mask = self.original_data[column] > value
                        else:  # 小于
                            mask = self.original_data[column] < value
                    except ValueError:
                        self.show_warning(f"无法将 '{search_text}' 转换为数值")
                        return

            # 更新过滤后的数据
            self.filtered_data = self.original_data[mask]

            # 重新加载数据到表格
            self._load_data_to_table()

            if dialog:
                dialog.accept()

        except Exception as e:
            logging.error(f"执行搜索时出错: {e}")
            self.show_error("搜索过程中出现错误，请稍后重试。")

    def _export_table_data(self):
        """导出表格数据"""
        try:
            file_path, _ = QFileDialog.getSaveFileName(self, "导出数据", "", "CSV Files (*.csv);;Excel Files (*.xlsx)")
            if file_path:
                if file_path.endswith('.csv'):
                    self.filtered_data.to_csv(file_path, index=False)
                elif file_path.endswith('.xlsx'):
                    self.filtered_data.to_excel(file_path, index=False)
                self.show_info("数据导出成功！")
        except Exception as e:
            logging.error(f"导出数据时出错: {e}")
            self.show_error("数据导出失败，请稍后重试。")

    def _refresh_table(self):
        """刷新表格数据"""
        try:
            self.filtered_data = self.original_data.copy()
            self._load_data_to_table()
            self.show_info("表格数据已刷新！")
        except Exception as e:
            logging.error(f"刷新表格数据时出错: {e}")
            self.show_error("表格数据刷新失败，请稍后重试。")

    def _show_stats_charts(self):
        """显示统计图表"""
        self._update_visualization()

    def _show_table_context_menu(self, position):
        """显示表格上下文菜单"""
        menu = QMenu(self)
        # 可以在这里添加更多上下文菜单选项
        menu.exec_(self.table_view.viewport().mapToGlobal(position))

    def show_info(self, message):
        """显示信息消息框"""
        QMessageBox.information(self, "信息", message)